#include "../include/pool.hpp"

void Pool::addTasks(_Task* task){
    tasks.addTasks(task);               // 不需要阻塞，队列内部有锁
    pool_cond.notify_one();             // 从线程池中调度一个线程，干活
}

/* 线程池初始化以及创建线程 */
Pool::Pool(int now_nums,int max_nums):now_nums(now_nums),max_nums(max_nums),idle_nums(now_nums),busy_nums(0),shutdown(false){
    threads=new(std::nothrow) std::thread[max_nums];
    if(threads==nullptr){
        printf("线程池创建失败...\n");
        abort;
    }
    memset(threads,0,sizeof(threads));
    manageID=std::thread(manage,this);
    
    for(int i=0;i<now_nums;i++){
        threads[i]=std::thread(worker,this);
        threads[i].detach();
    }
    DBGprint("create %d thread...\n",now_nums);
    printf("create %d thread...\n",now_nums);

}

/* 析构线程池 需要释放thread[] */
Pool::~Pool(){
    delete[] threads;
}


/* 线程管理函数 用于通知销毁函数 销毁函数的条件是将 唤醒 shutThead */
void* Pool::manage(void* arg){
    Pool *pool=static_cast<Pool*>(arg);
    wlock lck(pool->mtx);
    pool->shutThead.wait(lck);
    pool->shutdown=true;               // 将销毁标志位置1
    pool->pool_cond.notify_all();  // 告诉所以在阻塞的线程，该销毁了
    while(pool->now_nums){
        pool->shutThead.wait_for(lck,std::chrono::nanoseconds(1000));  // 阻塞1000纳秒后进行判断，线程是否运行完毕 
    }
    /* 以上运行完毕后，manage 关闭 */
    return nullptr;
}

void* Pool::worker(void* arg){
    Pool* pool=static_cast<Pool*>(arg);
    while(1){
        {
            wlock wlck(pool->mtx);
            if(pool->shutdown==true){
                pool->idle_nums--;
                pool->now_nums--;  // 当前线程数量-1
                return nullptr;   
            }
            // 线程进入阻塞等待中
            if(pool->tasks.getSize()==0){
                printf("tid=%d 重新回到线程池 %d %d\n",std::this_thread::get_id(),pool->busy_nums,pool->idle_nums);
                pool->pool_cond.wait(wlck);   // 等待唤醒
                if(pool->shutdown==true){  // 线程被唤醒后，判断是否是销毁信号，是的话就将当前线程任务终结  
                    pool->now_nums--;
                    pool->idle_nums--;
                    return nullptr;
                }

            }
        }

        {
            // 取任务
            _Task* task=pool->tasks.getTasks();
            {
                wlock wlck(pool->mtx);
                pool->busy_nums++;
                pool->idle_nums--;
            }

            if(task!=nullptr){
                task->fun((void*) task);
                delete task;
            }
            
            {
                // 完成任务
                wlock wlck(pool->mtx);
                pool->busy_nums--;
                pool->idle_nums++;
            }
        }
        printf("完成任务\n");
    }
    return nullptr;
}